﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace DynamicHeader
{
    /// <summary>Add references of JavaScript files and style sheet files into head elemenet at runtime.</summary>
    public class DynamicHeader
    {
        /// <summary>Get the instance of DynamicHeader at current request.</summary>
        public static DynamicHeader GetInstance()
        {
            const string key = "fa9b4c81993f4f7c9207be8c5c3de7b8";
            var contextItems = HttpContext.Current.Items;
            var instance = contextItems[key];
            if (instance != null) return instance as DynamicHeader;
            lock (key)
            {
                instance = contextItems[key];
                if (instance == null)
                {
                    instance = new DynamicHeader();
                    contextItems[key] = instance;
                }
                return instance as DynamicHeader;
            }
        }

        /// <summary>Add a reference of JavaScript file path.</summary>
        /// <param name="scriptPath">The path of JavaScript file to include, such as "~/Scripts/foo.js".</param>
        public static void AddScript(string scriptPath)
        {
            var scripts = DynamicHeader.GetInstance().Scripts;
            lock (scripts)
            {
                if (scripts.Any(path => path.Equals(scriptPath, StringComparison.InvariantCultureIgnoreCase)) == false)
                {
                    scripts.Add(scriptPath);
                }
            }
        }

        /// <summary>Add a reference if style sheet file path.</summary>
        /// <param name="styleSheetPath">The path of .css file to include, such as "~/Content/foo.css".</param>
        public static void AddStyleSheet(string styleSheetPath)
        {
            var styleSheets = DynamicHeader.GetInstance().StyleSheets;
            lock (styleSheets)
            {
                if (styleSheets.Any(path => path.Equals(styleSheetPath, StringComparison.InvariantCultureIgnoreCase)) == false)
                {
                    styleSheets.Add(styleSheetPath);
                }
            }
        }

        private List<string> Scripts { get; set; }
        
        private List<string> StyleSheets { get; set; }

        internal bool IsWritenSignature { get; set; }

        public DynamicHeader()
        {
            this.Scripts = new List<string>();
            this.StyleSheets = new List<string>();
            this.IsWritenSignature = false;
        }

        internal string GetHtml()
        {
            var appVirPath = HttpRuntime.AppDomainAppVirtualPath;
            if (appVirPath == "/") appVirPath = "";
            Func<string, string> resolveUrl = (url) => url.StartsWith("~/") ? appVirPath + url.Substring(1) : url;

            var html = new StringBuilder();
            this.StyleSheets
                .ForEach(path =>
                {
                    html.AppendFormat(
                        @"<link rel=""stylesheet"" type=""text/css"" href=""{0}""/>",
                        resolveUrl(path));
                });
            this.Scripts
                .ForEach(path =>
                {
                    html.AppendFormat(
                        @"<script type=""text/javascript"" src=""{0}""></script>",
                        resolveUrl(path));
                });

            return html.ToString();
        }
    }
}
